﻿// Trixter by mahe4
// but lovly stolen from fifty pence ;P (with permission)
//
// As always, if you wish to reuse code, please seek permission first 
// and provide credit where appropriate

using System;
using System.Linq;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Drawing;

using Styx;
using Styx.Combat.CombatRoutine;
using Styx.Helpers;
using Styx.Logic;
using Styx.Logic.Combat;
using Styx.Logic.Pathing;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;

using CommonBehaviors.Actions;
using TreeSharp;
using Action = TreeSharp.Action;

namespace Magomat
{
    public class Magomat : CombatRoutine
    {

        public override sealed string Name { get { return "Magomat v0.9.2"; } }
        public override WoWClass Class { get { return WoWClass.Mage; } }

        private static LocalPlayer Me { get { return ObjectManager.Me; } }

        public override void Initialize()
        {
            Logging.Write("");
            Logging.Write("Magomat v0.9.2 is now operational.");
            Logging.Write("All Credits are going to:");
            Logging.Write("fiftypence for his MutaRaidBT");
            Logging.Write("strix for some LazyRogue Methodes");
            Logging.Write("");
            Logging.Write("");
            
        }

        #region Variables

        // *********************************************************************
        // * Change Settings here!!!                                           *
        // *********************************************************************
        private Boolean UseKillingSpree = false;
        // *********************************************************************
        // * Dont change something below, if you don't know what you are doing *
        // *********************************************************************
        private List<WoWUnit> adds = new List<WoWUnit>();
        
        
        private WoWUnit lasttarget = null;
        private double CurrentMana = 0;
        private WoWPlayer FocusTarget = null;

        #endregion

        #region Combat




        private Composite _CombatBehavior;

        public override Composite CombatBehavior 
        { 
            get 
            {
                if (_CombatBehavior == null)
                {
                    Logging.Write("Building behavior tree.");

                    _CombatBehavior = BuildBehaviorTree();
                }

                return _CombatBehavior; 
            } 
        }

        private Composite BuildBehaviorTree()
        {
            return new Decorator(ret => !Me.Mounted && Me.CurrentTarget != null && !(Me.ChanneledCastingSpellId == 12051) && !(Me.ChanneledCastingSpellId == 5143),
                new PrioritySelector(
                    new Action(delegate {
                        UpdateMana();
                        adds = detectAdds();
                        //Logging.Write("AOE Count [[" + FireCount2() + "]]");
                        
                        
                        return RunStatus.Failure; }),

                        new Decorator(ret => SpellManager.HasSpell(44425),
                            new PrioritySelector(
                                
                                CastSpell("Counterspell", a => Me.CurrentTarget.IsCasting && Me.CanInterruptCurrentSpellCast && IsTargetBoss()),
                                CastSpell("Mage Armor", a => !PlayerHasBuff("Mage Armor")),
                                CastSpell("Arcane Brilliance", a => !PlayerHasBuff("Arcane Brilliance")),
                                CastSpell("Presence of Mind", a => !PlayerHasBuff("Arcane Potency")),
                                CastSpell("Flame Orb", a => true),
                                CastSpell("Evocation", a => CurrentMana < 35),
                                CastArcanePower(a => CurrentMana < 90 && SpellCooldown("Evocation") < 25 && IsTargetBoss()),
                                CastSpell("Mirror Image", a => CurrentMana < 90 && SpellCooldown("Evocation") < 25 && IsTargetBoss()),
                                CastSpell("Arcane Missiles", a => PlayerHasBuff("Arcane Missiles!") && CurrentMana < 94 && SpellCooldown("Evocation") > 25 && !Me.IsMoving),
                                CastSpell("Arcane Barrage", a => !PlayerHasBuff("Arcane Missiles!") && PlayerHasBuff("Arcane Blast") && Me.ActiveAuras["Arcane Blast"].StackCount >= 3 && CurrentMana < 94 && SpellCooldown("Evocation") > 20),
                                CastSpell("Arcane Barrage", a => Me.IsMoving),
                                CastSpell("Fireblast", a => Me.IsMoving),
                                CastSpell("Ice Lance", a => Me.IsMoving),
                                CastSpell("Arcane Blast", a => !Me.IsMoving)
                            )
                        ),

                        new Decorator(ret => SpellManager.HasSpell(11366),
                            new PrioritySelector(
                                CastSpell("Molten Armor", a => !PlayerHasBuff("Molten Armor") && CurrentMana >=35),
                                CastSpell("Mage Armor", a => !PlayerHasBuff("Mage Armor") && CurrentMana <= 20),
                                CastSpell("Molten Armor", a => !PlayerHasBuff("Molten Armor") && !PlayerHasBuff("Mage Armor")),
                                CastSpell("Arcane Brilliance", a => !PlayerHasBuff("Arcane Brilliance")),
                                CastSpell("Evocation", a => CurrentMana < 34),
                                UseBagItem("Mana Gem", a => CurrentMana < 90 && IsTargetBoss()),
                                new Decorator(ret => IsTargetBoss() || adds.Count < 3,
                                    new PrioritySelector(
                                        CastSpell("Counterspell", a => Me.CurrentTarget.IsCasting && Me.CanInterruptCurrentSpellCast && IsTargetBoss()),
                                        CastSpell("Mirror Image", a => IsTargetBoss()),
                                        CastPyroblast( a => PlayerHasBuff("Hot Streak") && (Me.IsCasting && Me.CurrentCastTimeLeft.Milliseconds > 500 || !Me.IsCasting)),
                                        CastSpell("Combustion", a => TargetDebuffTimeLeft("Pyroblast!") > 0 && TargetDebuffTimeLeft("Ignite") > 0 && TargetDebuffTimeLeft("Living Bomb") > 0),
                                        CastSpell("Scorch", a => !PlayerHasBuff("Hot Streak") && TargetDebuffTimeLeftAll("Winter's Chill") < 2 && TargetDebuffTimeLeftAll("Critical Mass") < 2 && TargetDebuffTimeLeftAll("Shadow and Flame") < 2 && !Me.IsInRaid),
                                        CastSpell("Living Bomb", a => TargetDebuffTimeLeft("Living Bomb") == 0),
                                        CastSpell("Flame Orb", a => true),
                                        CastSpell("Fire Blast", a => (TargetDebuffTimeLeft("Ignite") > 1 || TargetDebuffTimeLeft("Pyroblast!") > 3 || TargetDebuffTimeLeft("Living Bomb") > 4) && PlayerHasBuff("Impact") && !IsTargetBoss() && adds.Count > 1),
                                        CastSpell("Scorch", a => !PlayerHasBuff("Hot Streak") && (PlayerHasBuff("Mage Armor") || (!IsTargetBoss() && !Me.IsInRaid))),
                                        CastSpell("Fireball", a => !PlayerHasBuff("Hot Streak") && !Me.IsMoving),
                                        CastSpell("Scorch", a => !PlayerHasBuff("Hot Streak") && Me.IsMoving),
                                        CastSpell("Fireball", a => true)
                                    )
                                ),
                                new Decorator(ret => !IsTargetBoss() && adds.Count > 2,
                                    new PrioritySelector(
                                        CastSpell("Combustion", a => TargetDebuffTimeLeft("Pyroblast!") > 0 && TargetDebuffTimeLeft("Ignite") > 0 && TargetDebuffTimeLeft("Living Bomb") > 0 && Me.CurrentTarget.HealthPercent > 50),
                                        CastSpell("Fire Blast", a => (TargetDebuffTimeLeft("Ignite") >1 || TargetDebuffTimeLeft("Pyroblast!") > 1 || TargetDebuffTimeLeft("Living Bomb") > 1) && PlayerHasBuff("Impact")),
                                        CastBlastWave( a => true),
                                        CastSpell("Dragon's Breath", a => Me.CurrentTarget.Distance <= 12),
                                        CastFlamestrike(a => true),
                                        CastPyroblast( a => PlayerHasBuff("Hot Streak")),
                                        CastSpell("Living Bomb", a => !TargetHasDeBuff("Living Bomb")),
                                        CastSpell("Scorch", a => !PlayerHasBuff("Hot Streak"))

                                    )
                                )

                            )
                        )


                    
                   
                    
                )
            );
        }

        #endregion

        #region Helpers

        //******************************************************************************************
        //* The following helpers may be reused at will, as long as credit is given to fiftypence. *
        //******************************************************************************************

        #region Non-BT Helpers

        /// <summary>
        ///     List of nearby enemy units that pass certain criteria, this list should only return units 
        ///     in active combat with the player, the player's party, or the player's raid.
        /// </summary>

        private List<WoWUnit> EnemyUnits
        {
            get
            {
                return
                    ObjectManager.GetObjectsOfType<WoWUnit>(true, false)
                    .Where(unit =>
                        !unit.IsFriendly
                        && (unit.IsTargetingMeOrPet
                           || unit.IsTargetingMyPartyMember
                           || unit.IsTargetingMyRaidMember
                           || unit.IsPlayer)
                        && !unit.IsNonCombatPet
                        && !unit.IsCritter
                        && unit.Distance2D
                     <= 12).ToList();
            }
        }

        /// <summary>
        ///     Uses Lua to update current energy resource of the player. This is used
        ///     to fix the slow updating of ObjectManager.Me.CurrentMana.
        /// </summary>

        private void UpdateMana()
        {
            CurrentMana = Lua.GetReturnVal<double>("return (UnitMana(\"player\") / UnitManaMax(\"player\")) * 100;", 0);
            
            
        }

        /// <summary>
        ///     Uses Lua to find the GUID of the player's focus target then updates the 
        ///     global WoWPlayer FocusTarget to the new unit if appropriate. 
        /// </summary>
        
        

        /// <summary>
        ///     Uses WoWMathHelper to ensure we are behind the target.
        ///     A 2 radians cone is tested against. We must be within 1.34r (behind target) to return true.
        ///     Hopefully this should fix HonorBuddy's IsBehind bug.
        /// </summary>

        

        /// <summary>
        ///     Checks to see if specified target is under the effect of crowd control
        /// </summary>
        /// <param name="target">Target</param>
        /// <returns></returns>

        private bool IsCrowdControlled(WoWUnit target)
        {
            // Just want to throw a shout-out to Singular for this function.
            return target.GetAllAuras().Any(
            unit => unit.Spell.Mechanic == WoWSpellMechanic.Banished
                || unit.Spell.Mechanic == WoWSpellMechanic.Charmed
                || unit.Spell.Mechanic == WoWSpellMechanic.Horrified
                || unit.Spell.Mechanic == WoWSpellMechanic.Incapacitated
                || unit.Spell.Mechanic == WoWSpellMechanic.Polymorphed
                || unit.Spell.Mechanic == WoWSpellMechanic.Sapped
                || unit.Spell.Mechanic == WoWSpellMechanic.Shackled
                || unit.Spell.Mechanic == WoWSpellMechanic.Asleep
                || unit.Spell.Mechanic == WoWSpellMechanic.Frozen
            );
        }

        /// <summary>
        ///     Checks to see if any nearby units are under breakable crowd control.
        /// </summary>

        private bool ShouldWeAoe()
        {
            foreach (WoWUnit unit in EnemyUnits)
            {
                if (IsCrowdControlled(unit))
                {
                    return false;
                }
            }

            return true;
        }

        /// <summary>
        ///     Check if player has specified active buff using Lua.
        /// </summary>
        /// <param name="BuffName"></param>

        private bool PlayerHasBuff(string BuffName)
        {
            string BuffNameLua = Lua.GetReturnValues(string.Format("local name = UnitBuff(\"player\", \"{0}\"); " +
                                                 "return name", BuffName))[0];

            if (BuffNameLua == BuffName) return true;
            else return false;
        }

        private int PlayerBuffStack(string BuffName)
        {
            var lua = string.Format("local name = UnitBuff(\"player\", \"{0}\"); return count", Lua.Escape(BuffName));
            try
            {
                return int.Parse(Lua.GetReturnValues(lua)[0]);
            }
            catch
            {
                Logging.Write("Lua failed in BuffStack: " + lua);
                return 0;
            }
            
        }

        private bool TargetHasBuff(string BuffName)
        {
            string BuffNameLua = Lua.GetReturnValues(string.Format("local name = UnitBuff(\"target\", \"{0}\"); " +
                                                 "return name", BuffName))[0];

            if (BuffNameLua == BuffName) return true;
            else return false;
        }

        private bool TargetHasDeBuff(string BuffName)
        {
            string BuffNameLua = Lua.GetReturnValues(string.Format("local name = UnitDebuff(\"target\", \"{0}\"); " +
                                                 "return name", BuffName))[0];

            if (BuffNameLua == BuffName) return true;
            else return false;
        }

        /// <summary>
        ///     Returns the duration of a buff on the player
        /// </summary>
        /// <param name="DebuffName"></param>

        private double PlayerBuffTimeLeft(string BuffName)
        {
            return double.Parse(Lua.GetReturnValues(string.Format("local expirationTime = select(7, UnitBuff(\"player\", \"{0}\", nil, \"player\")); " +
                                     "if expirationTime == nil then return 0 else return expirationTime - GetTime() end", BuffName))[0]);
        }

        /// <summary>
        ///     Check if target has specified debuff using Lua, and returns the time remaining on the debuff.
        /// </summary>
        /// <param name="DebuffName"></param>

        private double TargetDebuffTimeLeft(string DebuffName)
        {
            return double.Parse(Lua.GetReturnValues(string.Format("local expirationTime = select(7, UnitDebuff(\"target\", \"{0}\", nil, \"player\")); " +
                                     "if expirationTime == nil then return 0 else return expirationTime - GetTime() end", DebuffName))[0]);
        }

        private double TargetDebuffTimeLeftAll(string DebuffName)
        {
            return double.Parse(Lua.GetReturnValues(string.Format("local expirationTime = select(7, UnitDebuff(\"target\", \"{0}\", nil)); " +
                                     "if expirationTime == nil then return 0 else return expirationTime - GetTime() end", DebuffName))[0]);
        }

        /// <summary>
        ///     Gets the cooldown of specified spell using Lua
        /// </summary>
        /// <param name="SpellName">Specified Spell</param>
        /// <returns>Spell cooldown</returns>

        public double SpellCooldown(string name)
        {
            var lua = string.Format("local x,y=GetSpellCooldown(\"{0}\"); return x+y-GetTime()", Lua.Escape(name));
            try
            {
                return double.Parse(Lua.GetReturnValues(lua)[0]);
            }
            catch
            {
                Logging.Write("Lua failed in SpellCooldown: " + lua);
                return 99999;
            }
        }

        /// <summary>
        ///     Check if player's target is a boss using Lua.
        /// </summary>

        private bool IsTargetBoss()
        {
            string UnitClassification = Lua.GetReturnValues("local classification = UnitClassification(\"target\"); return classification")[0];
            string UnitLevel = Lua.GetReturnValues("local level = UnitLevel(\"target\"); return level")[0];
            if (!Me.IsInRaid)
            {
                if (UnitClassification == "worldboss" ||
                   (Me.CurrentTarget.Level == 87 && Me.CurrentTarget.Elite) ||
                   (Me.CurrentTarget.Level == 88) ||
                   (UnitLevel == "-1"))
                    return true;

                else return false;
            }
            else
            {
                if (UnitLevel == "-1")
                    return true;

                else return false;
            }
            
            
        }

        /// <summary>
        ///     Returns true if a spell is not on cooldown or if
        ///     there is 0.3 or less left on GCD, AND the spell is known
        /// </summary>

        private bool CanCastSpell(string SpellName)
        {
            return (SpellCooldown(SpellName) <= 0.3 && SpellManager.HasSpell(SpellName));
        }

        #endregion

        #region BT Helpers

        #region Cast Spell

        /// <summary>
        ///     Checks if specified spell is castable, if so casts it and writes to log.
        /// </summary>
        /// <param name="SpellName">Spell name</param>
        /// <returns></returns>

        public Composite CastSpell(string SpellName)
        {
            return new Decorator(ret => Me.CurrentTarget != null && CanCastSpell(SpellName),
                new Action(delegate {
                    Lua.DoString(String.Format("CastSpellByName(\"{0}\");", SpellName));
                    Logging.Write("[" + CurrentMana + "] [" + Me.ComboPoints + "] " + SpellName); })
                    );
        }

        /// <summary>
        ///     Checks if specified spell is castable, if so casts it and writes to log.
        ///     Uses specified conditions.
        /// </summary>
        /// <param name="SpellName">Spell name</param>
        /// <param name="Conditions">Specified conditions</param>
        /// <returns></returns>

        public Composite CastSpell(string SpellName, CanRunDecoratorDelegate Conditions)
        {
            return new Decorator(ret => Conditions(ret) && CanCastSpell(SpellName),
                new Action(delegate {
                    Lua.DoString(String.Format("CastSpellByName(\"{0}\");", SpellName));
                    Logging.Write("[" + CurrentMana + "] "+ SpellName); })
            );
        }

        public Composite UseBagItem(string name, CanRunDecoratorDelegate cond)
        {
            WoWItem item = null;
            return new Decorator(
                delegate(object a)
                {
                    if (!cond(a))
                        return false;
                    item = Me.BagItems.FirstOrDefault(x => x.Name == name && x.Usable && x.Cooldown <= 0);
                    return item != null;
                },
                new Sequence(
                    new TreeSharp.Action(a => Logging.Write(name)),
                    new TreeSharp.Action(a => item.UseContainerItem())
                )
            );
        }


        
        /// <summary>
        ///     Checks if specified spell is castable, if so casts it and writes to log.
        ///     Casts on focus
        /// </summary>
        /// <param name="SpellName">Spell name</param>
        /// <returns></returns>

        #endregion

        #region Cast Focus

        public Composite CastSpellOnFocus(string SpellName)
        {
            return new Decorator(ret => FocusTarget != null && !FocusTarget.Dead && SpellManager.CanCast(SpellName, FocusTarget),
                new Action(delegate {
                SpellManager.Cast(SpellName, FocusTarget);
                Logging.Write(SpellName); })
            );
        }

        /// <summary>
        ///     Checks if specified spell is castable, if so casts it and writes to log.
        ///     Casts on focus, uses specified conditions
        /// </summary>
        /// <param name="SpellName">Spell name</param>
        /// <param name="Conditions">Specified conditions</param>
        /// <returns></returns>

        public Composite CastSpellOnFocus(string SpellName, CanRunDecoratorDelegate Conditions)
        {
            return new Decorator(ret => Conditions(ret) && FocusTarget != null && SpellManager.CanCast(SpellName, FocusTarget),
                new Action(delegate {
                SpellManager.Cast(SpellName, FocusTarget);
                Logging.Write(SpellName); })
            );
        }

        #endregion

        #region Cast Cooldowns

        /// <summary>
        ///     Checks if specified cooldown is castable, if so casts it and writes to log.
        ///     Casts with Lua to make use of the ability queue.
        /// </summary>
        /// <param name="SpellName">Cooldown name</param>
        /// <returns></returns>

        public Composite CastCooldown(string CooldownName)
        {
            return new Decorator(ret => CanCastSpell(CooldownName),
                new Action(delegate {
                Lua.DoString(String.Format("CastSpellByName(\"{0}\");", CooldownName));
                Logging.Write(CooldownName); })
            );
        }

        /// <summary>
        ///     Checks if specified cooldown is castable, if so casts it and writes to log.
        ///     Uses specified conditions.
        ///     Casts with Lua to make use of the ability queue.
        /// </summary>
        /// <param name="SpellName">Cooldown name</param>
        /// <param name="Conditions">Specified conditions</param>
        /// <returns></returns>

        public Composite CastCooldown(string CooldownName, CanRunDecoratorDelegate Conditions)
        {
            return new Decorator(ret => Conditions(ret) && CanCastSpell(CooldownName),
                new Action(delegate {
                Lua.DoString(String.Format("CastSpellByName(\"{0}\");", CooldownName));
                Logging.Write(CooldownName); })
            );
        }

        #endregion

        /// <summary>
        ///     Checks if player is auto-attacking, and if not toggles auto-attack.
        /// </summary>
        /// <returns></returns>

        public Composite AutoAttack()
        {
            return new Decorator(ret => !Me.IsAutoAttacking,
                new Action(delegate {
                    Me.ToggleAttack();
                    Logging.Write("Auto-attack"); })
            );
        }

        /// <summary>
        ///     Checks if player is auto-attacking, and if not toggles auto-attack.
        ///     Uses specified conditions.
        /// </summary>
        /// <returns></returns>

        public Composite AutoAttack(CanRunDecoratorDelegate Conditions)
        {
            return new Decorator(ret => Conditions(ret) && !Me.IsAutoAttacking,
                new Action(delegate {
                Me.ToggleAttack();
                Logging.Write("Auto-attack"); })
            );
        }

        #endregion

        #region LazyRogue-Helpers
        private List<WoWUnit> GetHostileInRange(int range, bool CCSensitive, bool IgnoreBanish)
        {
            List<WoWUnit> enemyMobList = new List<WoWUnit>();
            List<WoWUnit> mobList = ObjectManager.GetObjectsOfType<WoWUnit>(false);
            foreach (WoWUnit thing in mobList)
            {
                if (thing.Distance > range + 5 ||
                    thing.IsTotem ||
                   !thing.IsAlive ||
                   !thing.IsHostile ||
                    (thing.HasAura("Banish") && IgnoreBanish) ||
                   !thing.GotTarget
                   )
                {
                    continue;
                }

                if (CCSensitive && IsCrowdControlled(thing))
                {
                    enemyMobList.Clear();
                    return enemyMobList;
                }
                else if (thing.Distance < range + 1)
                    enemyMobList.Add(thing);
            }
            return enemyMobList;
        }

        private List<WoWUnit> GetHostileInRange(int range, bool CCSensitive, bool IgnoreBanish, WoWPoint fromLocation)
        {
            List<WoWUnit> enemyMobList = new List<WoWUnit>();
            List<WoWUnit> mobList = ObjectManager.GetObjectsOfType<WoWUnit>(false);
            foreach (WoWUnit thing in mobList)
            {
                if (thing.Location.Distance(fromLocation) > range + 5 ||
                    thing.IsTotem ||
                   !thing.IsAlive ||
                   !thing.IsHostile ||
                    (thing.HasAura("Banish") && IgnoreBanish) ||
                   !thing.GotTarget
                   )
                {
                    continue;
                }

                if (CCSensitive && IsCrowdControlled(thing))
                {
                    enemyMobList.Clear();
                    return enemyMobList;
                }
                else if (thing.Location.Distance(fromLocation) < range + 1)
                    enemyMobList.Add(thing);
            }
            return enemyMobList;
        }
        #endregion

        #region MyHelpers
        public Composite JustCastSpell(string SpellName, CanRunDecoratorDelegate Conditions)
        {
            return new Decorator(ret => Conditions(ret),
                new Action(delegate
            {
                Lua.DoString(String.Format("CastSpellByName(\"{0}\");", SpellName));
                Logging.Write("[" + CurrentMana + "] [" + Me.ComboPoints + "] " + SpellName);
            })
            );
        }

        public Composite CastArcanePower(CanRunDecoratorDelegate Conditions)
        {
            return new Decorator(ret => Conditions(ret) && CanCastSpell("Arcane Power"),
                new Action(delegate
                {
                    Lua.DoString(String.Format("CastSpellByName(\"{0}\");", "Arcane Power"));
                    Logging.Write("[" + CurrentMana + "] " + "Arcane Power");
                    Lua.DoString(String.Format("RunMacroText(\"/use Mana Gem\")"));
                    Lua.DoString(String.Format("RunMacroText(\"/use 13\")"));
                    Lua.DoString(String.Format("RunMacroText(\"/use 14\")"));
                    Lua.DoString(String.Format("RunMacroText(\"/use 10\")"));
                    Lua.DoString(String.Format("RunMacroText(\"/use Lifeblood\")"));
                })
            );
        }

        public Composite CastPyroblast(CanRunDecoratorDelegate Conditions)
        {
            return new Decorator(ret => Conditions(ret) ,
                new Action(delegate
                {
                    Lua.DoString(String.Format("RunMacroText(\"/stopcasting\")"));
                    Lua.DoString(String.Format("RunMacroText(\"/use Pyroblast!\")"));
                    Logging.Write("[" + CurrentMana + "] " + "Pyroblast!");
                    
                    
                })
            );
        }


        private List<WoWUnit> detectAdds()
        {
            if (Me.CurrentTarget != null)
            {
                List<WoWUnit> addList = ObjectManager.GetObjectsOfType<WoWUnit>(false).FindAll(unit =>
                            unit.Guid != Me.Guid &&
                            unit.Location.Distance(Me.CurrentTarget.Location) < 14 &&
                            (unit.IsTargetingMyPartyMember || unit.IsTargetingMyRaidMember || unit.IsTargetingMeOrPet) &&
                            !unit.IsFriendly &&
                            !unit.IsPet &&
                            !Styx.Logic.Blacklist.Contains(unit.Guid));

                
                return addList;
            }
            else
            {
                return null;
            }

        }

        public Composite CastAOE(string SpellName,CanRunDecoratorDelegate Conditions)
        {
            return new Decorator(ret => Conditions(ret) && CanCastSpell(SpellName),
                new Action(delegate
                {
                    Lua.DoString(String.Format("CastSpellByName(\"{0}\");", SpellName));
                    LegacySpellManager.ClickRemoteLocation(StyxWoW.Me.CurrentTarget.Location);
                    Logging.Write("[" + CurrentMana + "] " + SpellName);


                })
            );
        }

        public Composite CastFlamestrike(CanRunDecoratorDelegate Conditions)
        {
            return new Decorator(ret => Conditions(ret) && CanCastSpell("Flamestrike") && FireCount2() == 0,
                new Action(delegate
                {
                    Lua.DoString(String.Format("CastSpellByName(\"Flamestrike\");"));
                    LegacySpellManager.ClickRemoteLocation(StyxWoW.Me.CurrentTarget.Location);
                                        
                    Logging.Write("[" + CurrentMana + "] " + "Flamestrike");
                    
                    
                    
                    


                })
            );
        }

        public Composite CastBlastWave(CanRunDecoratorDelegate Conditions)
        {
            return new Decorator(ret => Conditions(ret) && CanCastSpell("Blast Wave"),
                new Action(delegate
                {
                    Lua.DoString(String.Format("CastSpellByName(\"Blast Wave\");"));
                    LegacySpellManager.ClickRemoteLocation(StyxWoW.Me.CurrentTarget.Location);
                    Lua.DoString(String.Format("CastSpellByName(\"Blast Wave\");"));
                    LegacySpellManager.ClickRemoteLocation(StyxWoW.Me.CurrentTarget.Location);
                    Lua.DoString(String.Format("CastSpellByName(\"Blast Wave\");"));
                    LegacySpellManager.ClickRemoteLocation(StyxWoW.Me.CurrentTarget.Location);
                    Logging.Write("[" + CurrentMana + "] " + "Blast Wave");
                    
                    
                    


                })
            );
        }
        

        

        public int FireCount2()
        {
            int fires = 0;
            List<WoWDynamicObject> AllO = new List<WoWDynamicObject>();
            AllO = ObjectManager.GetObjectsOfType<WoWDynamicObject>();
            
            int i = 0;
            while (i < AllO.Count)
            {
                if (AllO[i].Spell.Id == 2120 && AllO[i].CasterGuid == Me.Guid)
                {
                    fires++;
                    
                }
                
                i++;
            }
            
            return fires;
            
        }
        #endregion 
        #endregion
    }
}
